package com.ebs.md.fxmonitor.marketmonitor.esper.func;

/**
 * Perforce Revision:
 *  $File: //depot/MarketData/fxmonitor/main/src/main/java/com/ebs/md/fxmonitor/marketmonitor/esper/func/Functions.java $
 *  $Revision: #7 $  $Change: 116347 $  $DateTime: 2012/10/29 16:28:25 $  $Author: Arik.Sher $
 */

import java.util.Calendar;
import java.util.TimeZone;

import com.ebs.md.api.Rate;
import com.ebs.md.api.comparators.MdComparators;
import com.ebs.md.fxmonitor.marketmonitor.model.TOBState;


public final class Functions
{
	private Functions() {}
	
	
	/**
	 * @return is rate1 greater than rate2
	 */
	public static boolean isRateGreater(Rate rate1, Rate rate2) {
		int compare = MdComparators.offerRateComperator.compare(rate1, rate2);
		
		return compare > 0;
	}
	
	/**
	 * @return is rate1 lower than rate2
	 */
	public static boolean isRateLower(Rate rate1, Rate rate2) {
		int compare = MdComparators.offerRateComperator.compare(rate1, rate2);
		
		return compare < 0;
	}
	
	/**
	 * @return is rate1 equals rate2
	 */
	public static boolean isRateEqual(Rate rate1, Rate rate2) {
		int compare = MdComparators.offerRateComperator.compare(rate1, rate2);
		
		return compare == 0;
	}
	
	/**
	 * @return is bid rate1 better than rate2
	 */
	public static boolean isBidBetter(Rate rate1, Rate rate2) {
		int compare = MdComparators.bidRateComperator.compare(rate1, rate2);
		
		return compare < 0;
	}
	
	/**
	 * @return is offer rate1 better than rate2
	 */
	public static boolean isOfferBetter(Rate rate1, Rate rate2) {
		int compare = MdComparators.offerRateComperator.compare(rate1, rate2);
		
		return compare < 0;
	}

	public static boolean isBetweenSpread(Rate rate1, Rate rate2) {
		int compare = MdComparators.offerRateComperator.compare(rate1, rate2);
		
		return compare < 0;
	}

	/**
	 * should do the check only if there's a spread(best bid and offer are not empty)
	 * 
	 * @return is theRate between (exclusive) bestBid and bestOffer
	 */
	public static boolean isRateBetweenTheSpread(Rate bestBidRate, Rate bestOfferRate, Rate theRate) {
		boolean res = false;
		
		if ( 	bestBidRate   == null 
			|| 	bestOfferRate == null
			||	theRate == null ) {
			return false;
		}
		
		if (    true
			 && isBidBetter  (theRate, bestBidRate   )
			 && isOfferBetter(theRate, bestOfferRate )
			 )
		{
			res = true;
		}
		
		return res; 
	}

	/**
	 * @return is theRate between (exclusive) bestBid and bestOffer
	 */
	public static boolean isRateBetweenTheSpread(TOBState tob, Rate theRate) {
		if ( tob == null ) return false;
		
		return isRateBetweenTheSpread(tob.getBestBid(), tob.getBestOffer(), theRate);
	}

	// see http://stackoverflow.com/questions/7303580/understanding-etc-gmt-timezone
	final static TimeZone gmtTZ = TimeZone.getTimeZone("GMT0");
	
	/**
	 * 
	 * @param cQuoteGmt time.
	 * @param cFrom - calendar object which contain only HH:MM:SS
	 * @param cTo   - calendar object which contain only HH:MM:SS
	 * 
	 * @return set cFrom, cTo : with year, and day in month.
	 */
	private static void setToAndFromCalendars(Calendar cQuoteGmt, Calendar cFrom, Calendar cTo) 
	{
		cFrom.set(Calendar.YEAR,         cQuoteGmt.get(Calendar.YEAR));
		cFrom.set(Calendar.MONTH,        cQuoteGmt.get(Calendar.MONTH));
		cFrom.set(Calendar.DAY_OF_MONTH, cQuoteGmt.get(Calendar.DAY_OF_MONTH));

		cTo.set(Calendar.YEAR,         cQuoteGmt.get(Calendar.YEAR));
		cTo.set(Calendar.MONTH,        cQuoteGmt.get(Calendar.MONTH));
		cTo.set(Calendar.DAY_OF_MONTH, cQuoteGmt.get(Calendar.DAY_OF_MONTH));

		// why do we need this if?
		// answer: if cFrom=23:00:00 and cTo=06:00:00 then the 23:00:00 should be for the day before.
		if (cFrom.get(Calendar.HOUR_OF_DAY) > cTo.get(Calendar.HOUR_OF_DAY)) {
			// reduce single day from cFrom, so will always have cFrom < cTo !
			cFrom.add(Calendar.DAY_OF_MONTH, -1);
		}
	}

	/**
	 *  @param: quoteTimestamp - the time the quote was created.
	 *  @param: blackoutTimeFrom - time which contains HH:MM:SS only. (blackout at specific region)
	 *  @param: blackoutTimeTo   - time which contains HH:MM:SS only. (blackout at specific region)
	 *  
	 *  @return true if the quoteTimestamp is between the timeTo and timeFrom.
	 *  
	 *  Note: all times are GMT0
	 */
	public static boolean isTimeBetweenBlackoutHours(long quoteTimestamp, long blackoutTimeFrom, long blackoutTimeTo)
	{
		boolean isItBetweenBlackoutHours = false;
		
		Calendar cQuote = Calendar.getInstance(gmtTZ);
		Calendar cFrom  = Calendar.getInstance(gmtTZ);
		Calendar cTo    = Calendar.getInstance(gmtTZ);

		cQuote.setTimeInMillis(quoteTimestamp);
		cFrom .setTimeInMillis(blackoutTimeFrom);
		cTo   .setTimeInMillis(blackoutTimeTo);

		setToAndFromCalendars(cQuote, cFrom, cTo);

		if ( ( cFrom.before(cQuote) || cFrom.equals(cQuote) ) &&
			 ( cQuote.before(cTo)   || cQuote.equals(cTo)   ) )
		{
			isItBetweenBlackoutHours = true;
		}
		
		return isItBetweenBlackoutHours;
	}

}
